/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package iluscodelogica;

import java.io.*;
import java.util.HashMap;

/**
 * 
 * Clase que realiza el analisis lexico del algoritmo
 * recibe como parametro un reader
 * 
 * 
 * @author IlusCode Software para aprender a programar
 */
public class IlusLexer {

    Reader reader;
    StreamTokenizer tokenizer;
    int lienaActual = 0;
    HashMap simbolos;
    Token tokenActual;
    Token sacarToken;

    /**
     * 
     * Constructor de la clase
     * inicializa el objeto StreamTokenizer 
     * 
     * @param rdr
     * @throws IOException
     */
    public IlusLexer(Reader rdr) throws IOException {

        reader = rdr;
        simbolos = new HashMap();
        tokenizer = new StreamTokenizer(reader);
        tokenizer.lowerCaseMode(true);
        tokenizer.eolIsSignificant(true);
        tokenizer.slashStarComments(true);
        tokenActual = getSiguienteToken();
    }
    
     public IlusLexer(String archivo) throws IOException {

        //FileReader fr=new FileReader(archivo);
        //BufferedReader b=new BufferedReader(fr);
        this(new BufferedReader(new FileReader(archivo)));
       

    }

 
    /*
     * 
     * Metodo que recorre el objeto StreamTokenizer
     * 
     * 
     */

    private Token getSiguienteToken() throws IOException {

        int tokenTipo = tokenizer.nextToken();
        
        
        switch (tokenTipo) {
            //Caso que sea el fin del archivo
            case StreamTokenizer.TT_EOF:
                return new Token(TipoToken.EOF, "");
            //Caso que sea el fin de linea                
            case StreamTokenizer.TT_EOL:
                lienaActual += 1;
                return getSiguienteToken();
            //Caso que sea un número
            case StreamTokenizer.TT_NUMBER:
                if (tokenizer.nval != 0.0) {
                    return new Token(TipoToken.NUMERO, (int) tokenizer.nval);
                }
            //Caso que sea una palabra
            case StreamTokenizer.TT_WORD:
                //Buscar si es palabra clave
                PalabraClave pres = PalabraClave.buscarPalabra(tokenizer.sval);

                if (pres != null) {
                    return new Token(pres.getTipoToken(), pres.getToken());
                }
                //Buscar si es una acción
                Accion acc = Accion.buscarAccion(tokenizer.sval);
                if (acc != null) {
                    //Buscar si es una lectura de sensores
                    if (acc.getId() == TipoToken.DETECTA) {
                        return new Token(TipoToken.DETECTA, acc.getToken());
                    } else {
                        return new Token(TipoToken.ACCION, acc.getToken());
                    }
                }
                //Si no es ninguna corresponde a nombre de un procedimiento
                return new Token(TipoToken.NOMBRE, tokenizer.sval);


            default:

                StringBuilder sb = new StringBuilder();
                sb.append((char) tokenTipo);
                return new Token(TipoToken.CHAR, sb.toString());
        }
    }

  
    public boolean sacarToken(Token tk) {

        if (sacarToken == null) {
            sacarToken = tk;
        } else {
            throw (new IllegalArgumentException("Ya se ha sacado el token"));
        }
        return true;
    }

  
    public Token verToken() {
        if (sacarToken == null) {
            return tokenActual;
        } else {
            return sacarToken;
        }
    }

  
    public Token siguienteToken() throws IOException {
        if (sacarToken == null) {
            Token value = tokenActual;
            tokenActual = getSiguienteToken();
            return value;
        } else {
            Token value = sacarToken;
            sacarToken = null;
            return value;
        }
    }

   
    public void insertarSimbolo(String symbol, int cod) {
        String sym = symbol.intern();
        simbolos.put(sym, new Simbolo(sym, cod));
    }

 
    public Simbolo buscarSimbolo(String simbolo) {

        Simbolo s = (Simbolo) simbolos.get(simbolo.intern());
        return s;
    }

   
    public Token getTokenActual() {
        return tokenActual;
    }
}
